package com.zbs.framework.dao.permission.service.impl;

import com.zbs.framework.common.utils.ErrEnum;
import com.zbs.framework.common.utils.ErrorAssert;
import com.zbs.framework.dao.permission.entity.Permission;
import com.zbs.framework.dao.permission.repository.PermissionRepository;
import com.zbs.framework.dao.permission.service.PermissionService;
import com.zbs.framework.dao.permission.service.model.ServicePermission;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * Created by Zbs
 * 2019-04-28 11:38
 */
@Service
@Transactional
public class PermissionServiceImpl implements PermissionService {

    @Autowired
    private PermissionRepository permissionRepository;

    @Override
    public Permission save(String serviceName, String name, String description,
                           String extra,String path, boolean overwriteAllowed) {
        // 参数检查
        ErrorAssert.hasLength(serviceName, "Service name can not be empty!");
        ErrorAssert.hasLength(name, "Name can not be empty!");
        ErrorAssert.hasLength(path, "path can not be empty!");
        Permission permission = permissionRepository.findByServiceNameAndNameAndPath(serviceName, name,path);
        // 不允许覆盖时查重
        ErrorAssert.isTrue(overwriteAllowed || (permission == null), ErrEnum.PERMISSION_NAME_DUPLICATED);
        // 新增
        if (permission == null) {
            // 新增
            permission = new Permission(serviceName, name, description, extra,path);
            permissionRepository.save(permission);
        } else {
            // 修改信息
            if (!Objects.equals(permission.getDescription(), description) ||
                    !Objects.equals(permission.getExtra(), extra)) {
                // 描述或额外信息变化
                permission.setDescription(description);
                permission.setExtra(extra);
                permissionRepository.save(permission);
            }
        }
        return permission;
    }

    @Override
    public void edit(Long id, String serviceName, String name, String description, String extra,String path) {
        // 参数检查
        ErrorAssert.notNull(id, "Id can not be null!");
        ErrorAssert.hasLength(serviceName, "Service name can not be empty!");
        ErrorAssert.hasLength(name, "Name can not be empty!");
        // 检查分类是否存在
        Permission permission = permissionRepository.findById(id).orElse(null);
        ErrorAssert.notNull(permission, "Permission not exist!");
        if ((!name.equals(permission.getName())) || (!serviceName.equals(permission.getServiceName()))) {
            ErrorAssert.isTrue(isNameAva(serviceName, name), ErrEnum.PERMISSION_NAME_DUPLICATED);
            // 修改服务名
            permission.setServiceName(serviceName);
            // 修改名称
            permission.setName(name);
            // 修改接口路径
            permission.setPath(path);
        }
        //
        permission.setServiceName(serviceName);
        permission.setDescription(description);
        permission.setExtra(extra);
        permissionRepository.save(permission);
    }

    @Override
    public void delete(Long id) {
        permissionRepository.deleteById(id);
    }

    @Override
    public List<ServicePermission> findServicePermissions(String serviceName) {
        List<Permission> permissions = findAll(serviceName);
        // 封装
        List<ServicePermission> spList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(permissions)) {
            for (Permission p : permissions) {
                ServicePermission sp = getServicePermission(spList, p.getServiceName());
                if (sp == null) {
                    sp = new ServicePermission();
                    sp.setServiceName(p.getServiceName());
                    spList.add(sp);
                }
                sp.addPermission(p);
            }
        }
        return spList;
    }

    @Override
    public List<Permission> findAllPerms() {
        return permissionRepository.findAll();
    }

    private ServicePermission getServicePermission(List<ServicePermission> spList, String serviceName) {
        if (CollectionUtils.isEmpty(spList)) return null;
        for (ServicePermission sp : spList) {
            if (sp.getServiceName().equals(serviceName)) return sp;
        }
        return null;
    }

    private List<Permission> findAll(String serviceName) {
        Specification<Permission> specification = new Specification<Permission>() {
            @Nullable
            @Override
            public Predicate toPredicate(Root<Permission> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> list = new ArrayList<>();
                // 所属服务名
                if (StringUtils.hasLength(serviceName)){
                    list.add(cb.equal(root.get("serviceName"), serviceName));
                }
                return cb.and(list.toArray(new Predicate[]{}));
            }
        };
        return permissionRepository.findAll(specification,
                Sort.by(Sort.Order.asc("serviceName"), Sort.Order.asc("name")));
    }



    /**
     * 检查名称是否可用
     *
     * @param serviceName
     * @param name
     * @return
     */
    private boolean isNameAva(String serviceName, String name) {
        Permission exist = permissionRepository.findByServiceNameAndName(serviceName, name);
        return exist == null;
    }
}
